package bank;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class Bankmanagement {                   //知识点2：类的声明
    private static Scanner sc = new Scanner(System.in);         //知识点3:类成员的访问控制（私有，只能被这个类本身访问）
    private static final String DB_URL = "jdbc:mysql://localhost:3306/bank_system?useSSL=false&serverTimezone=UTC";
    private static final String USER = "root";
    private static final String PASS = "123456";
    
    public static void main(String[] args) {
        menu();
    }
    
    public static void menu() {
        while (true) {
            System.out.println("\n-------------------欢迎进入银行储蓄系统----------------");
            System.out.println("-------------------请选择您的登录方式------------------");
            System.out.println("-------------------0、登陆管理员账户-----------------");
            System.out.println("-------------------1、登录用户账户-----------------");
            System.out.println("-------------------2、注册账户-----------------");
            System.out.println("-------------------3、退出系统-----------------");
            
            try {
                System.out.print("请输入您的选择（0-3）：");
                String select = sc.nextLine().trim();
                
                switch (select) {
                    case "0":
                        login();
                        break;
                    case "1":
                        login1();
                        break;
                    case "2":
                        register();
                        break;
                    case "3":
                        System.out.println("感谢使用，再见！");
                        return;
                    default:
                        System.out.println("无效的选择，请重新输入！");
                }
            } catch (Exception e) {
                System.out.println("输入错误，请重新输入！");
                sc.nextLine(); // 清除输入缓冲
            }
        }
    }
    
    private static void login() {
        System.out.println("\n=== 管理员登录 ===");
        System.out.print("请输入管理员账号：");
        String username = sc.nextLine().trim();
        System.out.print("请输入密码：");
        String password = sc.nextLine().trim();
        
        // TODO: 实现管理员登录验证
        System.out.println("管理员登录功能待实现");
    }
    
    private static void login1() {
        System.out.println("\n=== 用户登录 ===");
        System.out.print("请输入卡号：");
        String cardId = sc.nextLine().trim();
        System.out.print("请输入密码：");
        String password = sc.nextLine().trim();
        
        try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS)) {
            String sql = "SELECT c.*, u.customername, d.savingname " +
                        "FROM cardinfo c " +
                        "JOIN userinfo u ON c.customerid = u.customerid " +
                        "JOIN deposit d ON c.savingid = d.savingid " +
                        "WHERE c.cardid = ? AND c.pass = ? AND c.isreportloss = '否'";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, cardId);
            pstmt.setString(2, password);
            ResultSet rs = pstmt.executeQuery();
            
            if (rs.next()) {
                System.out.println("登录成功！");
                System.out.println("欢迎您，" + rs.getString("customername"));
                System.out.println("卡号：" + rs.getString("cardid"));
                System.out.println("存款类型：" + rs.getString("savingname"));
                System.out.println("当前余额：" + rs.getBigDecimal("balance"));
                
                // 进入用户操作菜单
                userMenu(conn, cardId, rs.getInt("customerid"));
            } else {
                System.out.println("卡号或密码错误！");
            }
        } catch (SQLException e) {
            System.out.println("登录失败：" + e.getMessage());
        }
    }
    
    private static void userMenu(Connection conn, String cardId, int customerId) {
        while (true) {
            System.out.println("\n-------------------用户操作菜单----------------");
            System.out.println("1. 查询余额");
            System.out.println("2. 存款");
            System.out.println("3. 取款");
            System.out.println("4. 转账");
            System.out.println("5. 查询交易记录");
            System.out.println("6. 挂失/解挂");
            System.out.println("7. 修改密码");
            System.out.println("8. 申请新卡");
            System.out.println("9. 退出登录");
            
            System.out.print("请选择操作（1-9）：");
            String choice = sc.nextLine().trim();
            
            try {
                switch (choice) {
                    case "1":
                        queryBalance(conn, cardId);
                        break;
                    case "2":
                        deposit(conn, cardId);
                        break;
                    case "3":
                        withdraw(conn, cardId);
                        break;
                    case "4":
                        transfer(conn, cardId);
                        break;
                    case "5":
                        queryTransactions(conn, cardId);
                        break;
                    case "6":
                        reportLoss(conn, cardId);
                        break;
                    case "7":
                        changePassword(conn, cardId);
                        break;
                    case "8":
                        applyNewCard(conn, customerId);
                        break;
                    case "9":
                        return;
                    default:
                        System.out.println("无效的选择！");
                }
            } catch (SQLException e) {
                System.out.println("操作失败：" + e.getMessage());
            }
        }
    }
    
    private static void queryBalance(Connection conn, String cardId) throws SQLException {
        String sql = "SELECT balance FROM cardinfo WHERE cardid = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, cardId);
        ResultSet rs = pstmt.executeQuery();
        
        if (rs.next()) {
            System.out.println("当前余额：" + rs.getBigDecimal("balance"));
        }
    }
    
    private static void deposit(Connection conn, String cardId) throws SQLException {
        System.out.print("请输入存款金额：");
        double amount = Double.parseDouble(sc.nextLine().trim());
        
        if (amount <= 0) {
            System.out.println("存款金额必须大于0！");
            return;
        }
        
        conn.setAutoCommit(false);
        try {
            // 更新余额
            String sql1 = "UPDATE cardinfo SET balance = balance + ? WHERE cardid = ?";
            PreparedStatement pstmt1 = conn.prepareStatement(sql1);
            pstmt1.setDouble(1, amount);
            pstmt1.setString(2, cardId);
            pstmt1.executeUpdate();
            
            // 记录交易
            String sql2 = "INSERT INTO tradeinfo (tradedate, tradetype, cardid, trademoney, remark) " +
                         "VALUES (CURRENT_TIMESTAMP, '存款', ?, ?, '柜台存款')";
            PreparedStatement pstmt2 = conn.prepareStatement(sql2);
            pstmt2.setString(1, cardId);
            pstmt2.setDouble(2, amount);
            pstmt2.executeUpdate();
            
            conn.commit();
            System.out.println("存款成功！");
        } catch (SQLException e) {
            conn.rollback();
            throw e;
        }
    }
    
    private static void withdraw(Connection conn, String cardId) throws SQLException {
        System.out.print("请输入取款金额：");
        double amount = Double.parseDouble(sc.nextLine().trim());
        
        if (amount <= 0) {
            System.out.println("取款金额必须大于0！");
            return;
        }
        
        conn.setAutoCommit(false);
        try {
            // 检查余额
            String sql1 = "SELECT balance FROM cardinfo WHERE cardid = ? FOR UPDATE";
            PreparedStatement pstmt1 = conn.prepareStatement(sql1);
            pstmt1.setString(1, cardId);
            ResultSet rs = pstmt1.executeQuery();
            
            if (rs.next()) {
                double balance = rs.getDouble("balance");
                if (balance < amount) {
                    System.out.println("余额不足！");
                    return;
                }
                
                // 更新余额
                String sql2 = "UPDATE cardinfo SET balance = balance - ? WHERE cardid = ?";
                PreparedStatement pstmt2 = conn.prepareStatement(sql2);
                pstmt2.setDouble(1, amount);
                pstmt2.setString(2, cardId);
                pstmt2.executeUpdate();
                
                // 记录交易
                String sql3 = "INSERT INTO tradeinfo (tradedate, tradetype, cardid, trademoney, remark) " +
                             "VALUES (CURRENT_TIMESTAMP, '取款', ?, ?, '柜台取款')";
                PreparedStatement pstmt3 = conn.prepareStatement(sql3);
                pstmt3.setString(1, cardId);
                pstmt3.setDouble(2, amount);
                pstmt3.executeUpdate();
                
                conn.commit();
                System.out.println("取款成功！");
            }
        } catch (SQLException e) {
            conn.rollback();
            throw e;
        }
    }
    
    private static void transfer(Connection conn, String cardId) throws SQLException {
        System.out.print("请输入对方卡号：");
        String targetCardId = sc.nextLine().trim();
        System.out.print("请输入转账金额：");
        double amount = Double.parseDouble(sc.nextLine().trim());
        
        if (amount <= 0) {
            System.out.println("转账金额必须大于0！");
            return;
        }
        
        conn.setAutoCommit(false);
        try {
            // 检查余额
            String sql1 = "SELECT balance FROM cardinfo WHERE cardid = ? FOR UPDATE";
            PreparedStatement pstmt1 = conn.prepareStatement(sql1);
            pstmt1.setString(1, cardId);
            ResultSet rs = pstmt1.executeQuery();
            
            if (rs.next()) {
                double balance = rs.getDouble("balance");
                if (balance < amount) {
                    System.out.println("余额不足！");
                    return;
                }
                
                // 检查目标卡是否存在
                String sql2 = "SELECT 1 FROM cardinfo WHERE cardid = ? AND isreportloss = '否'";
                PreparedStatement pstmt2 = conn.prepareStatement(sql2);
                pstmt2.setString(1, targetCardId);
                if (!pstmt2.executeQuery().next()) {
                    System.out.println("目标卡号不存在或已挂失！");
                    return;
                }
                
                // 更新转出卡余额
                String sql3 = "UPDATE cardinfo SET balance = balance - ? WHERE cardid = ?";
                PreparedStatement pstmt3 = conn.prepareStatement(sql3);
                pstmt3.setDouble(1, amount);
                pstmt3.setString(2, cardId);
                pstmt3.executeUpdate();
                
                // 更新转入卡余额
                String sql4 = "UPDATE cardinfo SET balance = balance + ? WHERE cardid = ?";
                PreparedStatement pstmt4 = conn.prepareStatement(sql4);
                pstmt4.setDouble(1, amount);
                pstmt4.setString(2, targetCardId);
                pstmt4.executeUpdate();
                
                // 记录转出交易
                String sql5 = "INSERT INTO tradeinfo (tradedate, tradetype, cardid, trademoney, remark) " +
                             "VALUES (CURRENT_TIMESTAMP, '转账', ?, ?, ?)";
                PreparedStatement pstmt5 = conn.prepareStatement(sql5);
                pstmt5.setString(1, cardId);
                pstmt5.setDouble(2, amount);
                pstmt5.setString(3, "转账给" + targetCardId);
                pstmt5.executeUpdate();
                
                // 记录转入交易
                String sql6 = "INSERT INTO tradeinfo (tradedate, tradetype, cardid, trademoney, remark) " +
                             "VALUES (CURRENT_TIMESTAMP, '转账', ?, ?, ?)";
                PreparedStatement pstmt6 = conn.prepareStatement(sql6);
                pstmt6.setString(1, targetCardId);
                pstmt6.setDouble(2, amount);
                pstmt6.setString(3, "来自" + cardId + "的转账");
                pstmt6.executeUpdate();
                
                conn.commit();
                System.out.println("转账成功！");
            }
        } catch (SQLException e) {
            conn.rollback();
            throw e;
        }
    }
    
    private static void queryTransactions(Connection conn, String cardId) throws SQLException {
        String sql = "SELECT tradedate, tradetype, trademoney, remark " +
                    "FROM tradeinfo " +
                    "WHERE cardid = ? " +
                    "ORDER BY tradedate DESC";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, cardId);
        ResultSet rs = pstmt.executeQuery();
        
        System.out.println("\n交易记录：");
        System.out.println("交易时间\t\t交易类型\t交易金额\t备注");
        System.out.println("------------------------------------------------");
        while (rs.next()) {
            System.out.printf("%s\t%s\t%.2f\t%s\n",
                rs.getTimestamp("tradedate"),
                rs.getString("tradetype"),
                rs.getDouble("trademoney"),
                rs.getString("remark"));
        }
    }
    
    private static void reportLoss(Connection conn, String cardId) throws SQLException {
        String sql = "SELECT isreportloss FROM cardinfo WHERE cardid = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, cardId);
        ResultSet rs = pstmt.executeQuery();
        
        if (rs.next()) {
            String currentStatus = rs.getString("isreportloss");
            String newStatus = currentStatus.equals("否") ? "是" : "否";
            String operation = currentStatus.equals("否") ? "挂失" : "解挂";
            
            String sql2 = "UPDATE cardinfo SET isreportloss = ? WHERE cardid = ?";
            PreparedStatement pstmt2 = conn.prepareStatement(sql2);
            pstmt2.setString(1, newStatus);
            pstmt2.setString(2, cardId);
            pstmt2.executeUpdate();
            
            System.out.println(operation + "成功！");
        }
    }
    
    private static void changePassword(Connection conn, String cardId) throws SQLException {
        System.out.print("请输入原密码：");
        String oldPass = sc.nextLine().trim();
        System.out.print("请输入新密码（6位）：");
        String newPass = sc.nextLine().trim();
        
        if (newPass.length() != 6) {
            System.out.println("新密码必须是6位！");
            return;
        }
        
        String sql = "UPDATE cardinfo SET pass = ? WHERE cardid = ? AND pass = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, newPass);
        pstmt.setString(2, cardId);
        pstmt.setString(3, oldPass);
        
        int result = pstmt.executeUpdate();
        if (result > 0) {
            System.out.println("密码修改成功！");
        } else {
            System.out.println("原密码错误！");
        }
    }
    
    private static void applyNewCard(Connection conn, int customerId) throws SQLException {
        System.out.println("\n=== 申请新卡 ===");
        System.out.println("可选的存款类型：");
        
        // 显示存款类型
        String sql1 = "SELECT savingid, savingname, descrip FROM deposit";
        PreparedStatement pstmt1 = conn.prepareStatement(sql1);
        ResultSet rs = pstmt1.executeQuery();
        
        while (rs.next()) {
            System.out.printf("%d. %s - %s\n",
                rs.getInt("savingid"),
                rs.getString("savingname"),
                rs.getString("descrip"));
        }
        
        System.out.print("请选择存款类型（输入编号）：");
        int savingId = Integer.parseInt(sc.nextLine().trim());
        
        System.out.print("请输入开卡金额：");
        double openMoney = Double.parseDouble(sc.nextLine().trim());
        
        if (openMoney < 0) {
            System.out.println("开卡金额不能为负数！");
            return;
        }
        
        System.out.print("请设置密码（6位）：");
        String password = sc.nextLine().trim();
        
        if (password.length() != 6) {
            System.out.println("密码必须是6位！");
            return;
        }
        
        // 生成新卡号
        String cardId = generateCardId();
        
        // 创建新卡
        String sql2 = "INSERT INTO cardinfo (cardid, curid, savingid, opendate, openmoney, balance, pass, isreportloss, customerid) " +
                     "VALUES (?, 'RMB', ?, CURRENT_TIMESTAMP, ?, ?, ?, '否', ?)";
        PreparedStatement pstmt2 = conn.prepareStatement(sql2);
        pstmt2.setString(1, cardId);
        pstmt2.setInt(2, savingId);
        pstmt2.setDouble(3, openMoney);
        pstmt2.setDouble(4, openMoney);
        pstmt2.setString(5, password);
        pstmt2.setInt(6, customerId);
        pstmt2.executeUpdate();
        
        System.out.println("新卡申请成功！");
        System.out.println("您的卡号是：" + cardId);
        System.out.println("请妥善保管您的卡号和密码！");
    }
    
    private static void register() {
        System.out.println("\n=== 用户注册 ===");
        System.out.print("请输入姓名（最多8个字符）：");
        String name = sc.nextLine().trim();
        if (name.length() > 8) {
            System.out.println("姓名长度不能超过8个字符！");
            return;
        }
        
        System.out.print("请输入身份证号（18位）：");
        String pid = sc.nextLine().trim();
        if (pid.length() != 18) {
            System.out.println("身份证号必须是18位！");
            return;
        }
        
        System.out.print("请输入手机号：");
        String telephone = sc.nextLine().trim();
        
        System.out.print("请输入地址（可选）：");
        String address = sc.nextLine().trim();
        
        try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS)) {
            // 插入用户信息
            String sql1 = "INSERT INTO userinfo (customername, pid, telephone, address) VALUES (?, ?, ?, ?)";
            PreparedStatement pstmt1 = conn.prepareStatement(sql1, Statement.RETURN_GENERATED_KEYS);
            pstmt1.setString(1, name);
            pstmt1.setString(2, pid);
            pstmt1.setString(3, telephone);
            pstmt1.setString(4, address);
            pstmt1.executeUpdate();
            
            // 获取生成的客户ID
            ResultSet rs = pstmt1.getGeneratedKeys();
            if (!rs.next()) {
                throw new SQLException("创建用户失败，未获取到ID");
            }
            int customerId = rs.getInt(1);
            
            // 申请第一张卡
            applyNewCard(conn, customerId);
            
        } catch (SQLException e) {
            System.out.println("注册失败：" + e.getMessage());
        }
    }
    
    private static String generateCardId() {
        // 生成17位卡号：10103576 + 9位随机数
        StringBuilder cardId = new StringBuilder("10103576");
        Random random = new Random();
        for (int i = 0; i < 9; i++) {
            cardId.append(random.nextInt(10));
        }
        return cardId.toString();
    }
} 